bondscell_results0$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2queued¤logsrunning¦outputbodyټ

That's all you need! Pluto will synchronise the value of x with the latest value of the HTML input. Try moving the slider! 👆

mimetext/htmlrootassigneelast_run_timestampAڎʆpersist_js_state·has_pluto_hook_features§cell_id$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$beb9a2bd-cbf5-4679-8403-fc249191f65equeued¤logsrunning¦outputbody
mimetext/htmlrootassigneelast_run_timestampAڎʇ:persist_js_state·has_pluto_hook_features§cell_id$beb9a2bd-cbf5-4679-8403-fc249191f65edepends_on_disabled_cells§runtimeɵpublished_object_keysdepends_on_skipped_cells§errored$7b11caf2-1fc1-4e34-8b97-eab86e3557dbqueued¤logsrunning¦outputbody

Tip

In this example, we immediately call update() and trigger an input event with the initial value. If we didn't do that, the value of counter would be nothing until the first interaction. Whether that's appropriate, depends on the interaction you want. In this case, it made sense that the counter should start at 0!

mimetext/htmlrootassigneelast_run_timestampAڎʈ-persist_js_state·has_pluto_hook_features§cell_id$7b11caf2-1fc1-4e34-8b97-eab86e3557dbdepends_on_disabled_cells§runtime8̵published_object_keysdepends_on_skipped_cells§errored$cf9d49cc-fc70-480c-9f6b-850b0ba4c01fqueued¤logsrunning¦outputbodyt

The script is now keeping track of clicks, but it's not sending that value anywhere.

We need to:

mimetext/htmlrootassigneelast_run_timestampAڎʇΒpersist_js_state·has_pluto_hook_features§cell_id$cf9d49cc-fc70-480c-9f6b-850b0ba4c01fdepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$33b5374c-91d1-4122-82c5-f793d063ffdcqueued¤logsrunning¦outputbody@mimetext/htmlrootassigneelast_run_timestampAڎgpersist_js_state·has_pluto_hook_features§cell_id$33b5374c-91d1-4122-82c5-f793d063ffdcdepends_on_disabled_cells§runtime #published_object_keysdepends_on_skipped_cells§errored$4a235d55-a80f-43c7-8f13-759976d88656queued¤logsrunning¦outputbodyAmimetext/htmlrootassigneelast_run_timestampAڎf-persist_js_state·has_pluto_hook_features§cell_id$4a235d55-a80f-43c7-8f13-759976d88656depends_on_disabled_cells§runtime iJpublished_object_keysdepends_on_skipped_cells§errored$788c0b9b-238f-4402-b24f-52648103512equeued¤logsrunning¦outputbody

If you're looking for something more sophisticated than simple string interpolation, check out the HyperTextLiteral package!

mimetext/htmlrootassigneelast_run_timestampAڎʈfpersist_js_state·has_pluto_hook_features§cell_id$788c0b9b-238f-4402-b24f-52648103512edepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$2969d603-9b6c-403e-abdc-af078c2e53f1queued¤logsrunning¦outputbodyw
Let's make something interactive here!
mimetext/htmlrootassigneelast_run_timestampAڎʇd԰persist_js_state·has_pluto_hook_features§cell_id$2969d603-9b6c-403e-abdc-af078c2e53f1depends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$f39435d3-ed67-45f1-ae56-49cf5ec69d6equeued¤logsrunning¦outputbodymissingmimetext/plainrootassigneelast_run_timestampAڎΣppersist_js_state·has_pluto_hook_features§cell_id$f39435d3-ed67-45f1-ae56-49cf5ec69d6edepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$73c8532e-09a6-429b-b8f6-530c00d92428queued¤logsrunning¦outputbody

Interactivity with HTML

Pluto notebooks can use the @bind macro for interactive inputs. Neat!

If you're completely new to coding anything interactive in a web browser, the easiest way to get started is with the PlutoUI package in Julia. (Check out the PlutoUI featured notebook if you'd like to learn more about that!)

If you have some experience with HTML, or if you would like to learn how to make your own interactive elements, this notebook is for you! We'll cover the basics of using @bind with HTML elements. Let's get started!

mimetext/htmlrootassigneelast_run_timestampAڎʆiUpersist_js_state·has_pluto_hook_features§cell_id$73c8532e-09a6-429b-b8f6-530c00d92428depends_on_disabled_cells§runtime^published_object_keysdepends_on_skipped_cells§errored$1ebba747-47f8-4ecd-809d-359e6d803ddcqueued¤logsrunning¦outputbodymissingmimetext/plainrootassigneeylast_run_timestampAڎfpersist_js_state·has_pluto_hook_features§cell_id$1ebba747-47f8-4ecd-809d-359e6d803ddcdepends_on_disabled_cells§runtime/published_object_keysdepends_on_skipped_cells§errored$582769e6-7eb1-11ea-077d-d9b4a3226aacqueued¤logsrunning¦outputbody

Behind the scenes

If you're curious to learn a bit more about how this all works, keep reading!

The output value

As we've mentioned, bound values are just the latest value of the input element, rather than some kind of observable.

The update mechanism is lossy and lazy, which means that it will skip values if your code is still running - and only send the latest value when your code is ready again. This is important when changing a slider from 0 to 100, for example. If it would send all intermediate values, it might take a while for your code to process everything, causing a noticeable lag.

mimetext/htmlrootassigneelast_run_timestampAڎʉUpersist_js_state·has_pluto_hook_features§cell_id$582769e6-7eb1-11ea-077d-d9b4a3226aacdepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$de1b9643-66fa-4918-9a93-0f340c8548baqueued¤logsrunning¦outputbodyٲ

Now we can use the script to handle whatever interaction we want. For a simple element, let's add a button and count the number of clicks.

mimetext/htmlrootassigneelast_run_timestampAڎʇpersist_js_state·has_pluto_hook_features§cell_id$de1b9643-66fa-4918-9a93-0f340c8548badepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$82c7b1ea-08c0-495f-baba-37e5497abde2queued¤logsrunning¦outputbodyC

It's as simple as that!

mimetext/htmlrootassigneelast_run_timestampAڎʉGpersist_js_state·has_pluto_hook_features§cell_id$82c7b1ea-08c0-495f-baba-37e5497abde2depends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$cb65a4ee-02e5-4779-8728-b994d8af645dqueued¤logsrunning¦outputbodyMissingmimetext/plainrootassigneelast_run_timestampAڎc/persist_js_state·has_pluto_hook_features§cell_id$cb65a4ee-02e5-4779-8728-b994d8af645ddepends_on_disabled_cells§runtime&published_object_keysdepends_on_skipped_cells§errored$f558f689-bd7a-4c65-8b3d-b3681a4ed013queued¤logsrunning¦outputbody
mimetext/htmlrootassigneelast_run_timestampAڎΣMpersist_js_state·has_pluto_hook_features§cell_id$f558f689-bd7a-4c65-8b3d-b3681a4ed013depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$b6501bfb-5e1d-40b9-bd16-d38085d2611dqueued¤logsrunning¦outputbodyAmimetext/htmlrootassigneelast_run_timestampAڎgܰpersist_js_state·has_pluto_hook_features§cell_id$b6501bfb-5e1d-40b9-bd16-d38085d2611ddepends_on_disabled_cells§runtime Jpublished_object_keysdepends_on_skipped_cells§errored$ced18648-7eb2-11ea-2052-07795685f0daqueued¤logsrunning¦outputbodyd

JavaScript?

Yes! We are using Generator.input from observablehq/stdlib to create a JS Generator (kind of like an Observable) that listens to onchange, onclick or oninput events, depending on the element type.

This makes it super easy to create nice HTML/JS-based interaction elements - a package creator simply has to write a show method for MIME type text/html that creates a DOM object that triggers the input event. In other words, Pluto's @bind will behave exactly like viewof in observablehq.

If you want to learn more about using Javascript in Pluto, check out the JavaScript sample notebook!

mimetext/htmlrootassigneelast_run_timestampAڎʊ)Epersist_js_state·has_pluto_hook_features§cell_id$ced18648-7eb2-11ea-2052-07795685f0dadepends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$e2854aa0-e3c5-423d-80d9-fc875c5dd54dqueued¤logsrunning¦outputbodyٜ

Keep in mind that changing the value of limit will re-evaluate the slider cell, so it will reset the value.

mimetext/htmlrootassigneelast_run_timestampAڎʈsqpersist_js_state·has_pluto_hook_features§cell_id$e2854aa0-e3c5-423d-80d9-fc875c5dd54ddepends_on_disabled_cells§runtime9published_object_keysdepends_on_skipped_cells§errored$bd24d02c-7eac-11ea-14ab-95021678e71equeued¤logsrunning¦outputbody@mimetext/htmlrootassigneelast_run_timestampAڎpersist_js_state·has_pluto_hook_features§cell_id$bd24d02c-7eac-11ea-14ab-95021678e71edepends_on_disabled_cells§runtime&- published_object_keysdepends_on_skipped_cells§errored$0a7018ca-2afe-42b1-850f-a649e570709fqueued¤logsrunning¦outputbodyٖ

A neat aspect of this @bind macro is that on the Julia side, x is just a normal integer:

mimetext/htmlrootassigneelast_run_timestampAڎʆ޾persist_js_state·has_pluto_hook_features§cell_id$0a7018ca-2afe-42b1-850f-a649e570709fdepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$5301eb68-7f14-11ea-3ff6-1f075bf73955queued¤logsrunning¦outputbody

Input types

You can use binds with anything that fires an input event. For example:

mimetext/htmlrootassigneelast_run_timestampAڎʇ"persist_js_state·has_pluto_hook_features§cell_id$5301eb68-7f14-11ea-3ff6-1f075bf73955depends_on_disabled_cells§runtimexpublished_object_keysdepends_on_skipped_cells§errored$f595bdb6-bd15-4c62-9de6-49f14c7d365aqueued¤logsrunning¦outputbody?mimetext/htmlrootassigneelast_run_timestampAڎhѰpersist_js_state·has_pluto_hook_features§cell_id$f595bdb6-bd15-4c62-9de6-49f14c7d365adepends_on_disabled_cells§runtime  published_object_keysdepends_on_skipped_cells§errored$d5b3adc5-2c99-4901-adf5-8d8579a32b51queued¤logsrunning¦outputbody

Tip

Interpolating values in Javascript is neat, but remember that we are just taking the string representation of the variable and pasting it in the javascript code. For some complex data types like dates, you will need to do a bit of conversion to turn them into proper javascript expressions.

mimetext/htmlrootassigneelast_run_timestampAڎʈpersist_js_state·has_pluto_hook_features§cell_id$d5b3adc5-2c99-4901-adf5-8d8579a32b51depends_on_disabled_cells§runtimeӋpublished_object_keysdepends_on_skipped_cells§errored$c50a5e52-7c95-445c-86ee-c60104a39dbdqueued¤logsrunning¦outputbody

Using Julia values in HTML

We've seen how you can pass on values from an interactive HTML element on to Julia, but for proper interaction, we also want to do it the other way around!

The most basic way to do this is string interpolation. In this example, you can change the value of limit in the code to affect the maximum value of the slider. Try it out!

mimetext/htmlrootassigneelast_run_timestampAڎʈSpersist_js_state·has_pluto_hook_features§cell_id$c50a5e52-7c95-445c-86ee-c60104a39dbddepends_on_disabled_cells§runtimeTpublished_object_keysdepends_on_skipped_cells§errored$3b6dc6d5-ce96-40f6-97f7-511ea6d49122queued¤logsrunning¦outputbodymmimetext/htmlrootassigneelast_run_timestampAڎή($persist_js_state·has_pluto_hook_features§cell_id$3b6dc6d5-ce96-40f6-97f7-511ea6d49122depends_on_disabled_cells§runtime Dpublished_object_keysdepends_on_skipped_cells§errored$5bd8b261-a89d-46a3-bb59-c95a1801c881queued¤logsrunning¦outputbodymissingmimetext/plainrootassigneelast_run_timestampAڎΖpersist_js_state·has_pluto_hook_features§cell_id$5bd8b261-a89d-46a3-bb59-c95a1801c881depends_on_disabled_cells§runtime!ppublished_object_keysdepends_on_skipped_cells§errored$e3eb31ae-c512-426f-915c-01144edbc90dqueued¤logsrunning¦outputbody
mimetext/htmlrootassigneelast_run_timestampAڎΖXѰpersist_js_state·has_pluto_hook_features§cell_id$e3eb31ae-c512-426f-915c-01144edbc90ddepends_on_disabled_cells§runtimeqpublished_object_keysdepends_on_skipped_cells§errored$2cefd0de-db13-49c1-abeb-097792ef46f6queued¤logsrunning¦outputbody

For something even fancier, you can also interpolate value in Javascript. For example, here I have adapted my counter so it won't count past limit:

mimetext/htmlrootassigneelast_run_timestampAڎʈ}persist_js_state·has_pluto_hook_features§cell_id$2cefd0de-db13-49c1-abeb-097792ef46f6depends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$3297233b-9567-4d5e-8138-93ebe20fed48queued¤logsrunning¦outputbodyelementsmissingtext/plainmissingtext/plaintypeTupleobjectidffffffff944f3bacmime!application/vnd.pluto.tree+objectrootassigneelast_run_timestampAڎ׌persist_js_state·has_pluto_hook_features§cell_id$3297233b-9567-4d5e-8138-93ebe20fed48depends_on_disabled_cells§runtime`@published_object_keysdepends_on_skipped_cells§errored$cb1fd532-7eac-11ea-307c-ab16b1977819queued¤logsrunning¦outputbodymissingmimetext/plainrootassigneelast_run_timestampAڎSpersist_js_state·has_pluto_hook_features§cell_id$cb1fd532-7eac-11ea-307c-ab16b1977819depends_on_disabled_cells§runtime'`published_object_keysdepends_on_skipped_cells§errored$9985a640-c1d3-48dc-b00b-d7500085a37bqueued¤logsrunning¦outputbodyي mimetext/htmlrootassigneelast_run_timestampAڎgq;persist_js_state·has_pluto_hook_features§cell_id$9985a640-c1d3-48dc-b00b-d7500085a37bdepends_on_disabled_cells§runtime 豵published_object_keysdepends_on_skipped_cells§errored$816ea402-7eae-11ea-2134-fb595cca3068queued¤logsrunning¦outputbody

Not an observable, callback, or something else that you need to wrap your head around. You can use x like you would any other number, and Pluto's reactivity means anything depending on x will be updated with it. 🚀

mimetext/htmlrootassigneelast_run_timestampAڎʆmpersist_js_state·has_pluto_hook_features§cell_id$816ea402-7eae-11ea-2134-fb595cca3068depends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$d38d06f2-90ce-4e5a-9218-f5a52812e4a2queued¤logsrunning¦outputbodyDmimetext/htmlrootassigneelast_run_timestampAڎgF̰persist_js_state·has_pluto_hook_features§cell_id$d38d06f2-90ce-4e5a-9218-f5a52812e4a2depends_on_disabled_cells§runtimeϵpublished_object_keysdepends_on_skipped_cells§errored$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecfqueued¤logsrunning¦outputbodyق

Okay, now we can use this HTML snippet with a @bind macro and see the result!

mimetext/htmlrootassigneelast_run_timestampAڎʈ аpersist_js_state·has_pluto_hook_features§cell_id$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecfdepends_on_disabled_cells§runtime;published_object_keysdepends_on_skipped_cells§errored$1a338f77-d8f3-4569-a2d5-c174368a4761queued¤logsrunning¦outputbodyZ mimetext/htmlrootassigneelast_run_timestampAڎ΢޹persist_js_state·has_pluto_hook_features§cell_id$1a338f77-d8f3-4569-a2d5-c174368a4761depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$c5a5e243-39d6-43d9-8de7-887661ba99cdqueued¤logsrunning¦outputbodymmimetext/htmlrootassigneelast_run_timestampAڎέcpersist_js_state·has_pluto_hook_features§cell_id$c5a5e243-39d6-43d9-8de7-887661ba99cddepends_on_disabled_cells§runtime ppublished_object_keysdepends_on_skipped_cells§errored$ff3abf71-cff6-459d-a622-0ec0ca8f164bqueued¤logsrunning¦outputbodyf

This is is how the PlutoUI package works - it defines HTML literals - sometimes with their own scripts.

If you've written some cool HTML inputs and you want to share them with others, you can also make a UI package! Just publish those definitions as a Julia package and you're done! ✨

mimetext/htmlrootassigneelast_run_timestampAڎʉjnpersist_js_state·has_pluto_hook_features§cell_id$ff3abf71-cff6-459d-a622-0ec0ca8f164bdepends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$bb4b557b-e4fc-45f3-9d1f-060198167bfaqueued¤logsrunning¦outputbody

Reusing elements

Once you've written some neat interactive element, you may want to use it a few times in notebook. The easiest way is to put the HTML literal in a variable.

mimetext/htmlrootassigneelast_run_timestampAڎʈ&persist_js_state·has_pluto_hook_features§cell_id$bb4b557b-e4fc-45f3-9d1f-060198167bfadepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$8f829274-7eb1-11ea-3888-13c00b3ba70fqueued¤logsrunning¦outputbodyB

What does the macro do?

The @bind macro does not actually contain the interactivity mechanism, this is built into Pluto itself. Still, it does two things: it assigns a default value to the variable (missing in most cases), and it wraps the second argument in a PlutoRunner.Bond object.

For example, expanding the @bind macro turns this expression:

@bind x Slider(5:15)

into (simplified):

begin
    local el = Slider(5:15)
    global x = AbstractPlutoDingetjes.intial_value(el)
    PlutoRunner.create_bond(el, :x)
end

We see that the macro creates a variable x, which is given the value AbstractPlutoDingetjes.intial_value(el). This function returns missing by default, unless a method was implemented for your widget type. For example, PlutoUI has a Slider type, and it defines a method for intial_value(slider::Slider) that returns the default number.

Declaring a default value using AbstractPlutoDingetjes is not necessary, as shown by the earlier examples in this notebook, but the default value will be used for x if the notebook.jl file is run as a plain julia file, without Pluto's interactivity.

You don't need to worry about this if you are just getting started with Pluto and interactive elements, but more advanced users should take a look at AbstractPlutoDingetjes.jl.

mimetext/htmlrootassigneelast_run_timestampAڎʉpersist_js_state·has_pluto_hook_features§cell_id$8f829274-7eb1-11ea-3888-13c00b3ba70fdepends_on_disabled_cells§runtime |published_object_keysdepends_on_skipped_cells§errored$ede8009e-7f15-11ea-192a-a5c6135a9dcfqueued¤logsrunning¦outputbodyelementsmissingtext/plainmissingtext/plainmissingtext/plainmissingtext/plainmissingtext/plainmissingtext/plaintypeTupleobjectidffffffff2bb69edcmime!application/vnd.pluto.tree+objectrootassigneelast_run_timestampAڎΕpersist_js_state·has_pluto_hook_features§cell_id$ede8009e-7f15-11ea-192a-a5c6135a9dcfdepends_on_disabled_cells§runtime4еpublished_object_keysdepends_on_skipped_cells§errored$c1b9fbbb-3629-4abf-b11a-b7345b01d403queued¤logsrunning¦outputbody

Scripting inputs with Javascript

You can also use Javascript to write more complicated inputs.

To get started with this, add a <script> tag to your cell. The easiest setup is to make the script a child of the cell's root element. Then you can use currentScript.parentElement to select the script's parent element.

For instance, here a HTML snippet with a script added to it.

mimetext/htmlrootassigneelast_run_timestampAڎʇJpersist_js_state·has_pluto_hook_features§cell_id$c1b9fbbb-3629-4abf-b11a-b7345b01d403depends_on_disabled_cells§runtimex-published_object_keysdepends_on_skipped_cells§errored$f1f53700-099b-4653-93f1-6b39acdc4c58queued¤logsrunning¦outputbody
mimetext/htmlrootassigneelast_run_timestampAڎʇpersist_js_state·has_pluto_hook_features§cell_id$f1f53700-099b-4653-93f1-6b39acdc4c58depends_on_disabled_cells§runtimeipublished_object_keysdepends_on_skipped_cells§errored$2d8661f1-6f78-4161-a306-982e3ddf3646queued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAڎέpersist_js_state·has_pluto_hook_features§cell_id$2d8661f1-6f78-4161-a306-982e3ddf3646depends_on_disabled_cells§runtime0published_object_keysdepends_on_skipped_cells§errored$db24490e-7eac-11ea-094e-9d3fc8f22784queued¤logsrunning¦outputbodyD

Bound variables

A basic interactive cell looks like this: we use the @bind macro, define a Julia variable, and add a bit of HTML code that creates an <input> element. The HTML element will be rendered as the cell's output.

mimetext/htmlrootassigneelast_run_timestampAڎʆBpersist_js_state·has_pluto_hook_features§cell_id$db24490e-7eac-11ea-094e-9d3fc8f22784depends_on_disabled_cells§runtimespublished_object_keysdepends_on_skipped_cells§errored$901c2b84-14b8-4deb-89d6-705a4972582cqueued¤logsrunning¦outputbodymissingmimetext/plainrootassigneelast_run_timestampAڎΤXpersist_js_state·has_pluto_hook_features§cell_id$901c2b84-14b8-4deb-89d6-705a4972582cdepends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$2714a923-2be5-4cf9-97dd-75347968dfeequeued¤logsrunning¦outputbody5mimetext/plainrootassigneelimitlast_run_timestampAڎΚ 5persist_js_state·has_pluto_hook_features§cell_id$2714a923-2be5-4cf9-97dd-75347968dfeedepends_on_disabled_cells§runtime%ѵpublished_object_keysdepends_on_skipped_cells§errored$863c5996-9892-4bfc-96ba-225fa4a2266cqueued¤logsrunning¦outputbodyO

Tip

To avoid confusing your readers, it's a good idea to put a ; at the end of the cell where you define the interactive element, like we did here. This way, we only show sliders that are actually bound to something.

mimetext/htmlrootassigneelast_run_timestampAڎʉ>ypersist_js_state·has_pluto_hook_features§cell_id$863c5996-9892-4bfc-96ba-225fa4a2266cdepends_on_disabled_cells§runtime3published_object_keysdepends_on_skipped_cells§errored±cell_dependencies0$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2precedence_heuristic cell_id$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2downstream_cells_mapupstream_cells_map@md_strgetindex$beb9a2bd-cbf5-4679-8403-fc249191f65eprecedence_heuristic cell_id$beb9a2bd-cbf5-4679-8403-fc249191f65edownstream_cells_mapupstream_cells_mapBaseBase.Docs.HTML@html_str$7b11caf2-1fc1-4e34-8b97-eab86e3557dbprecedence_heuristic cell_id$7b11caf2-1fc1-4e34-8b97-eab86e3557dbdownstream_cells_mapupstream_cells_map@md_strgetindex$cf9d49cc-fc70-480c-9f6b-850b0ba4c01fprecedence_heuristic cell_id$cf9d49cc-fc70-480c-9f6b-850b0ba4c01fdownstream_cells_mapupstream_cells_map@md_strgetindex$33b5374c-91d1-4122-82c5-f793d063ffdcprecedence_heuristic cell_id$33b5374c-91d1-4122-82c5-f793d063ffdcdownstream_cells_mapb$ede8009e-7f15-11ea-192a-a5c6135a9dcfupstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$4a235d55-a80f-43c7-8f13-759976d88656precedence_heuristic cell_id$4a235d55-a80f-43c7-8f13-759976d88656downstream_cells_mapa$ede8009e-7f15-11ea-192a-a5c6135a9dcfupstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$788c0b9b-238f-4402-b24f-52648103512eprecedence_heuristic cell_id$788c0b9b-238f-4402-b24f-52648103512edownstream_cells_mapupstream_cells_map@md_strgetindex$2969d603-9b6c-403e-abdc-af078c2e53f1precedence_heuristic cell_id$2969d603-9b6c-403e-abdc-af078c2e53f1downstream_cells_mapupstream_cells_mapBaseBase.Docs.HTML@html_str$f39435d3-ed67-45f1-ae56-49cf5ec69d6eprecedence_heuristic cell_id$f39435d3-ed67-45f1-ae56-49cf5ec69d6edownstream_cells_mapupstream_cells_maplimited$1a338f77-d8f3-4569-a2d5-c174368a4761$73c8532e-09a6-429b-b8f6-530c00d92428precedence_heuristic cell_id$73c8532e-09a6-429b-b8f6-530c00d92428downstream_cells_mapupstream_cells_map@md_strgetindex$1ebba747-47f8-4ecd-809d-359e6d803ddcprecedence_heuristic cell_id$1ebba747-47f8-4ecd-809d-359e6d803ddcdownstream_cells_mapyupstream_cells_map^x$bd24d02c-7eac-11ea-14ab-95021678e71e$582769e6-7eb1-11ea-077d-d9b4a3226aacprecedence_heuristic cell_id$582769e6-7eb1-11ea-077d-d9b4a3226aacdownstream_cells_mapupstream_cells_map@md_strgetindex$de1b9643-66fa-4918-9a93-0f340c8548baprecedence_heuristic cell_id$de1b9643-66fa-4918-9a93-0f340c8548badownstream_cells_mapupstream_cells_map@md_strgetindex$82c7b1ea-08c0-495f-baba-37e5497abde2precedence_heuristic cell_id$82c7b1ea-08c0-495f-baba-37e5497abde2downstream_cells_mapupstream_cells_map@md_strgetindex$cb65a4ee-02e5-4779-8728-b994d8af645dprecedence_heuristic cell_id$cb65a4ee-02e5-4779-8728-b994d8af645ddownstream_cells_mapupstream_cells_maptypeofx$bd24d02c-7eac-11ea-14ab-95021678e71e$f558f689-bd7a-4c65-8b3d-b3681a4ed013precedence_heuristic cell_id$f558f689-bd7a-4c65-8b3d-b3681a4ed013downstream_cells_maplimited_counter$901c2b84-14b8-4deb-89d6-705a4972582cupstream_cells_mapCoreBasePlutoRunner.create_bondPlutoRunnerHTMLCore.applicableBase.get@bindlimit$2714a923-2be5-4cf9-97dd-75347968dfee$b6501bfb-5e1d-40b9-bd16-d38085d2611dprecedence_heuristic cell_id$b6501bfb-5e1d-40b9-bd16-d38085d2611ddownstream_cells_mape$ede8009e-7f15-11ea-192a-a5c6135a9dcfupstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$ced18648-7eb2-11ea-2052-07795685f0daprecedence_heuristic cell_id$ced18648-7eb2-11ea-2052-07795685f0dadownstream_cells_mapupstream_cells_map@md_strgetindex$e2854aa0-e3c5-423d-80d9-fc875c5dd54dprecedence_heuristic cell_id$e2854aa0-e3c5-423d-80d9-fc875c5dd54ddownstream_cells_mapupstream_cells_map@md_strgetindex$bd24d02c-7eac-11ea-14ab-95021678e71eprecedence_heuristic cell_id$bd24d02c-7eac-11ea-14ab-95021678e71edownstream_cells_mapx$cb1fd532-7eac-11ea-307c-ab16b1977819$cb65a4ee-02e5-4779-8728-b994d8af645d$1ebba747-47f8-4ecd-809d-359e6d803ddcupstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$0a7018ca-2afe-42b1-850f-a649e570709fprecedence_heuristic cell_id$0a7018ca-2afe-42b1-850f-a649e570709fdownstream_cells_mapupstream_cells_map@md_strgetindex$5301eb68-7f14-11ea-3ff6-1f075bf73955precedence_heuristic cell_id$5301eb68-7f14-11ea-3ff6-1f075bf73955downstream_cells_mapupstream_cells_map@md_strgetindex$f595bdb6-bd15-4c62-9de6-49f14c7d365aprecedence_heuristic cell_id$f595bdb6-bd15-4c62-9de6-49f14c7d365adownstream_cells_mapf$ede8009e-7f15-11ea-192a-a5c6135a9dcfupstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$d5b3adc5-2c99-4901-adf5-8d8579a32b51precedence_heuristic cell_id$d5b3adc5-2c99-4901-adf5-8d8579a32b51downstream_cells_mapupstream_cells_map@md_strgetindex$c50a5e52-7c95-445c-86ee-c60104a39dbdprecedence_heuristic cell_id$c50a5e52-7c95-445c-86ee-c60104a39dbddownstream_cells_mapupstream_cells_map@md_strgetindex$3b6dc6d5-ce96-40f6-97f7-511ea6d49122precedence_heuristic cell_id$3b6dc6d5-ce96-40f6-97f7-511ea6d49122downstream_cells_mapx2$3297233b-9567-4d5e-8138-93ebe20fed48upstream_cells_mapCoreBasePlutoRunner.create_bondPlutoRunnerCore.applicablemyslider$2d8661f1-6f78-4161-a306-982e3ddf3646@bindBase.get$5bd8b261-a89d-46a3-bb59-c95a1801c881precedence_heuristic cell_id$5bd8b261-a89d-46a3-bb59-c95a1801c881downstream_cells_mapupstream_cells_mapcounter$e3eb31ae-c512-426f-915c-01144edbc90d$e3eb31ae-c512-426f-915c-01144edbc90dprecedence_heuristic cell_id$e3eb31ae-c512-426f-915c-01144edbc90ddownstream_cells_mapcounter$5bd8b261-a89d-46a3-bb59-c95a1801c881upstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$2cefd0de-db13-49c1-abeb-097792ef46f6precedence_heuristic cell_id$2cefd0de-db13-49c1-abeb-097792ef46f6downstream_cells_mapupstream_cells_map@md_strgetindex$3297233b-9567-4d5e-8138-93ebe20fed48precedence_heuristic cell_id$3297233b-9567-4d5e-8138-93ebe20fed48downstream_cells_mapupstream_cells_mapx1$c5a5e243-39d6-43d9-8de7-887661ba99cdx2$3b6dc6d5-ce96-40f6-97f7-511ea6d49122$cb1fd532-7eac-11ea-307c-ab16b1977819precedence_heuristic cell_id$cb1fd532-7eac-11ea-307c-ab16b1977819downstream_cells_mapupstream_cells_mapx$bd24d02c-7eac-11ea-14ab-95021678e71e$9985a640-c1d3-48dc-b00b-d7500085a37bprecedence_heuristic cell_id$9985a640-c1d3-48dc-b00b-d7500085a37bdownstream_cells_mapd$ede8009e-7f15-11ea-192a-a5c6135a9dcfupstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$816ea402-7eae-11ea-2134-fb595cca3068precedence_heuristic cell_id$816ea402-7eae-11ea-2134-fb595cca3068downstream_cells_mapupstream_cells_map@md_strgetindex$d38d06f2-90ce-4e5a-9218-f5a52812e4a2precedence_heuristic cell_id$d38d06f2-90ce-4e5a-9218-f5a52812e4a2downstream_cells_mapc$ede8009e-7f15-11ea-192a-a5c6135a9dcfupstream_cells_mapBasePlutoRunner.Base.get@html_str#PlutoRunner.PlutoRunner.create_bondPlutoRunnerBase.Docs.HTML@bindPlutoRunner.Core.applicable$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecfprecedence_heuristic cell_id$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecfdownstream_cells_mapupstream_cells_map@md_strgetindex$1a338f77-d8f3-4569-a2d5-c174368a4761precedence_heuristic cell_id$1a338f77-d8f3-4569-a2d5-c174368a4761downstream_cells_maplimited$f39435d3-ed67-45f1-ae56-49cf5ec69d6eupstream_cells_mapCoreBasePlutoRunner.create_bondPlutoRunnerHTMLCore.applicableBase.get@bindlimit$2714a923-2be5-4cf9-97dd-75347968dfee$c5a5e243-39d6-43d9-8de7-887661ba99cdprecedence_heuristic cell_id$c5a5e243-39d6-43d9-8de7-887661ba99cddownstream_cells_mapx1$3297233b-9567-4d5e-8138-93ebe20fed48upstream_cells_mapCoreBasePlutoRunner.create_bondPlutoRunnerCore.applicablemyslider$2d8661f1-6f78-4161-a306-982e3ddf3646@bindBase.get$ff3abf71-cff6-459d-a622-0ec0ca8f164bprecedence_heuristic cell_id$ff3abf71-cff6-459d-a622-0ec0ca8f164bdownstream_cells_mapupstream_cells_map@md_strgetindex$bb4b557b-e4fc-45f3-9d1f-060198167bfaprecedence_heuristic cell_id$bb4b557b-e4fc-45f3-9d1f-060198167bfadownstream_cells_mapupstream_cells_map@md_strgetindex$8f829274-7eb1-11ea-3888-13c00b3ba70fprecedence_heuristic cell_id$8f829274-7eb1-11ea-3888-13c00b3ba70fdownstream_cells_mapupstream_cells_map@md_strgetindex$ede8009e-7f15-11ea-192a-a5c6135a9dcfprecedence_heuristic cell_id$ede8009e-7f15-11ea-192a-a5c6135a9dcfdownstream_cells_mapupstream_cells_mapf$f595bdb6-bd15-4c62-9de6-49f14c7d365ac$d38d06f2-90ce-4e5a-9218-f5a52812e4a2e$b6501bfb-5e1d-40b9-bd16-d38085d2611db$33b5374c-91d1-4122-82c5-f793d063ffdca$4a235d55-a80f-43c7-8f13-759976d88656d$9985a640-c1d3-48dc-b00b-d7500085a37b$c1b9fbbb-3629-4abf-b11a-b7345b01d403precedence_heuristic cell_id$c1b9fbbb-3629-4abf-b11a-b7345b01d403downstream_cells_mapupstream_cells_map@md_strgetindex$f1f53700-099b-4653-93f1-6b39acdc4c58precedence_heuristic cell_id$f1f53700-099b-4653-93f1-6b39acdc4c58downstream_cells_mapupstream_cells_mapBaseBase.Docs.HTML@html_str$2d8661f1-6f78-4161-a306-982e3ddf3646precedence_heuristic cell_id$2d8661f1-6f78-4161-a306-982e3ddf3646downstream_cells_mapmyslider$c5a5e243-39d6-43d9-8de7-887661ba99cd$3b6dc6d5-ce96-40f6-97f7-511ea6d49122upstream_cells_mapBaseBase.Docs.HTML@html_str$db24490e-7eac-11ea-094e-9d3fc8f22784precedence_heuristic cell_id$db24490e-7eac-11ea-094e-9d3fc8f22784downstream_cells_mapupstream_cells_map@md_strgetindex$901c2b84-14b8-4deb-89d6-705a4972582cprecedence_heuristic cell_id$901c2b84-14b8-4deb-89d6-705a4972582cdownstream_cells_mapupstream_cells_maplimited_counter$f558f689-bd7a-4c65-8b3d-b3681a4ed013$2714a923-2be5-4cf9-97dd-75347968dfeeprecedence_heuristic cell_id$2714a923-2be5-4cf9-97dd-75347968dfeedownstream_cells_maplimit$1a338f77-d8f3-4569-a2d5-c174368a4761$f558f689-bd7a-4c65-8b3d-b3681a4ed013upstream_cells_map$863c5996-9892-4bfc-96ba-225fa4a2266cprecedence_heuristic cell_id$863c5996-9892-4bfc-96ba-225fa4a2266cdownstream_cells_mapupstream_cells_map@md_strgetindexcell_execution_order0$73c8532e-09a6-429b-b8f6-530c00d92428$db24490e-7eac-11ea-094e-9d3fc8f22784$bd24d02c-7eac-11ea-14ab-95021678e71e$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2$cb1fd532-7eac-11ea-307c-ab16b1977819$0a7018ca-2afe-42b1-850f-a649e570709f$cb65a4ee-02e5-4779-8728-b994d8af645d$816ea402-7eae-11ea-2134-fb595cca3068$1ebba747-47f8-4ecd-809d-359e6d803ddc$5301eb68-7f14-11ea-3ff6-1f075bf73955$4a235d55-a80f-43c7-8f13-759976d88656$33b5374c-91d1-4122-82c5-f793d063ffdc$d38d06f2-90ce-4e5a-9218-f5a52812e4a2$9985a640-c1d3-48dc-b00b-d7500085a37b$b6501bfb-5e1d-40b9-bd16-d38085d2611d$f595bdb6-bd15-4c62-9de6-49f14c7d365a$ede8009e-7f15-11ea-192a-a5c6135a9dcf$c1b9fbbb-3629-4abf-b11a-b7345b01d403$2969d603-9b6c-403e-abdc-af078c2e53f1$de1b9643-66fa-4918-9a93-0f340c8548ba$f1f53700-099b-4653-93f1-6b39acdc4c58$cf9d49cc-fc70-480c-9f6b-850b0ba4c01f$beb9a2bd-cbf5-4679-8403-fc249191f65e$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecf$e3eb31ae-c512-426f-915c-01144edbc90d$5bd8b261-a89d-46a3-bb59-c95a1801c881$7b11caf2-1fc1-4e34-8b97-eab86e3557db$c50a5e52-7c95-445c-86ee-c60104a39dbd$2714a923-2be5-4cf9-97dd-75347968dfee$1a338f77-d8f3-4569-a2d5-c174368a4761$f39435d3-ed67-45f1-ae56-49cf5ec69d6e$e2854aa0-e3c5-423d-80d9-fc875c5dd54d$2cefd0de-db13-49c1-abeb-097792ef46f6$f558f689-bd7a-4c65-8b3d-b3681a4ed013$901c2b84-14b8-4deb-89d6-705a4972582c$d5b3adc5-2c99-4901-adf5-8d8579a32b51$788c0b9b-238f-4402-b24f-52648103512e$bb4b557b-e4fc-45f3-9d1f-060198167bfa$2d8661f1-6f78-4161-a306-982e3ddf3646$c5a5e243-39d6-43d9-8de7-887661ba99cd$3b6dc6d5-ce96-40f6-97f7-511ea6d49122$3297233b-9567-4d5e-8138-93ebe20fed48$82c7b1ea-08c0-495f-baba-37e5497abde2$863c5996-9892-4bfc-96ba-225fa4a2266c$ff3abf71-cff6-459d-a622-0ec0ca8f164b$582769e6-7eb1-11ea-077d-d9b4a3226aac$8f829274-7eb1-11ea-3888-13c00b3ba70f$ced18648-7eb2-11ea-2052-07795685f0dalast_hot_reload_timeshortpathInteractivity with HTML.jlprocess_statusreadypathQ/home/fons/featured-slider-server/featured_fix/src/web/Interactivity with HTML.jlpluto_versionv1.0.0last_save_timeAڎʃcell_order0$73c8532e-09a6-429b-b8f6-530c00d92428$db24490e-7eac-11ea-094e-9d3fc8f22784$bd24d02c-7eac-11ea-14ab-95021678e71e$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2$cb1fd532-7eac-11ea-307c-ab16b1977819$0a7018ca-2afe-42b1-850f-a649e570709f$cb65a4ee-02e5-4779-8728-b994d8af645d$816ea402-7eae-11ea-2134-fb595cca3068$1ebba747-47f8-4ecd-809d-359e6d803ddc$5301eb68-7f14-11ea-3ff6-1f075bf73955$4a235d55-a80f-43c7-8f13-759976d88656$33b5374c-91d1-4122-82c5-f793d063ffdc$d38d06f2-90ce-4e5a-9218-f5a52812e4a2$9985a640-c1d3-48dc-b00b-d7500085a37b$b6501bfb-5e1d-40b9-bd16-d38085d2611d$f595bdb6-bd15-4c62-9de6-49f14c7d365a$ede8009e-7f15-11ea-192a-a5c6135a9dcf$c1b9fbbb-3629-4abf-b11a-b7345b01d403$2969d603-9b6c-403e-abdc-af078c2e53f1$de1b9643-66fa-4918-9a93-0f340c8548ba$f1f53700-099b-4653-93f1-6b39acdc4c58$cf9d49cc-fc70-480c-9f6b-850b0ba4c01f$beb9a2bd-cbf5-4679-8403-fc249191f65e$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecf$e3eb31ae-c512-426f-915c-01144edbc90d$5bd8b261-a89d-46a3-bb59-c95a1801c881$7b11caf2-1fc1-4e34-8b97-eab86e3557db$c50a5e52-7c95-445c-86ee-c60104a39dbd$2714a923-2be5-4cf9-97dd-75347968dfee$1a338f77-d8f3-4569-a2d5-c174368a4761$f39435d3-ed67-45f1-ae56-49cf5ec69d6e$e2854aa0-e3c5-423d-80d9-fc875c5dd54d$2cefd0de-db13-49c1-abeb-097792ef46f6$f558f689-bd7a-4c65-8b3d-b3681a4ed013$901c2b84-14b8-4deb-89d6-705a4972582c$d5b3adc5-2c99-4901-adf5-8d8579a32b51$788c0b9b-238f-4402-b24f-52648103512e$bb4b557b-e4fc-45f3-9d1f-060198167bfa$2d8661f1-6f78-4161-a306-982e3ddf3646$c5a5e243-39d6-43d9-8de7-887661ba99cd$3b6dc6d5-ce96-40f6-97f7-511ea6d49122$3297233b-9567-4d5e-8138-93ebe20fed48$82c7b1ea-08c0-495f-baba-37e5497abde2$863c5996-9892-4bfc-96ba-225fa4a2266c$ff3abf71-cff6-459d-a622-0ec0ca8f164b$582769e6-7eb1-11ea-077d-d9b4a3226aac$8f829274-7eb1-11ea-3888-13c00b3ba70f$ced18648-7eb2-11ea-2052-07795685f0dajulia_versionv1.12.4published_objectsnbpkginstall_time_nsΨinstantiatedòinstalled_versions!__internal_julia_manifest_version1.12.4__internal_julia_version1.12.4terminal_outputsnbpkg_syncf Waiting for the package registry to update... === Resolving... ===  Project No packages added to or removed from `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_kfpimzpukk/Project.toml`  Manifest No packages added to or removed from `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_kfpimzpukk/Manifest.toml` Instantiating... === Precompiling... === Waiting for notebook process to start... Done. Starting precompilation...enabled÷restart_recommended_msgrestart_required_msgbusy_packageswaiting_for_permission,waiting_for_permission_but_probably_disabled«cell_inputs0$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2cell_id$cf72c8a2-7ead-11ea-32b7-d31d5b2dacc2codeًmd""" That's all you need! Pluto will synchronise the value of `x` with the latest value of the HTML input. Try moving the slider! 👆 """metadatashow_logsèdisabled®skip_as_script«code_folded$beb9a2bd-cbf5-4679-8403-fc249191f65ecell_id$beb9a2bd-cbf5-4679-8403-fc249191f65ecodehtml"""
"""metadatashow_logsèdisabled®skip_as_script«code_folded$7b11caf2-1fc1-4e34-8b97-eab86e3557dbcell_id$7b11caf2-1fc1-4e34-8b97-eab86e3557dbcodeTmd""" !!! tip In this example, we immediately call `update()` and trigger an input event with the initial value. If we didn't do that, the value of `counter` would be `nothing` until the first interaction. Whether that's appropriate, depends on the interaction you want. In this case, it made sense that the counter should start at 0! """metadatashow_logsèdisabled®skip_as_script«code_folded$cf9d49cc-fc70-480c-9f6b-850b0ba4c01fcell_id$cf9d49cc-fc70-480c-9f6b-850b0ba4c01fcodemd""" The script is now keeping track of clicks, but it's not sending that value anywhere. We need to: - Update the parent's element `value` property (this is what Pluto will be reading). - Dispatch an `"input"` event to trigger change detection. """metadatashow_logsèdisabled®skip_as_script«code_folded$33b5374c-91d1-4122-82c5-f793d063ffdccell_id$33b5374c-91d1-4122-82c5-f793d063ffdccode @bind b html""metadatashow_logsèdisabled®skip_as_script«code_folded$4a235d55-a80f-43c7-8f13-759976d88656cell_id$4a235d55-a80f-43c7-8f13-759976d88656code!@bind a html""metadatashow_logsèdisabled®skip_as_script«code_folded$788c0b9b-238f-4402-b24f-52648103512ecell_id$788c0b9b-238f-4402-b24f-52648103512ecodemd""" If you're looking for something more sophisticated than simple string interpolation, check out the [HyperTextLiteral package](https://juliapluto.github.io/HypertextLiteral.jl/stable/)! """metadatashow_logsèdisabled®skip_as_script«code_folded$2969d603-9b6c-403e-abdc-af078c2e53f1cell_id$2969d603-9b6c-403e-abdc-af078c2e53f1codeقhtml"""
Let's make something interactive here!
"""metadatashow_logsèdisabled®skip_as_script«code_folded$f39435d3-ed67-45f1-ae56-49cf5ec69d6ecell_id$f39435d3-ed67-45f1-ae56-49cf5ec69d6ecodelimitedmetadatashow_logsèdisabled®skip_as_script«code_folded$73c8532e-09a6-429b-b8f6-530c00d92428cell_id$73c8532e-09a6-429b-b8f6-530c00d92428code[md""" # Interactivity with HTML Pluto notebooks can use the `@bind` macro for interactive inputs. Neat! If you're completely new to coding anything interactive in a web browser, the easiest way to get started is with the `PlutoUI` package in Julia. (Check out the [PlutoUI featured notebook](https://featured.plutojl.org/basic/plutoui.jl) if you'd like to learn more about that!) If you have some experience with HTML, or if you would like to learn how to make your own interactive elements, this notebook is for you! We'll cover the basics of using `@bind` with HTML elements. Let's get started! """metadatashow_logsèdisabled®skip_as_script«code_folded$1ebba747-47f8-4ecd-809d-359e6d803ddccell_id$1ebba747-47f8-4ecd-809d-359e6d803ddccodey = x^2metadatashow_logsèdisabled®skip_as_script«code_folded$582769e6-7eb1-11ea-077d-d9b4a3226aaccell_id$582769e6-7eb1-11ea-077d-d9b4a3226aaccodevmd""" ## Behind the scenes If you're curious to learn a bit more about how this all works, keep reading! ### The output value As we've mentioned, bound values are just the latest value of the input element, rather than some kind of observable. The update mechanism is _lossy_ and _lazy_, which means that it will skip values if your code is still running - and **only send the latest value when your code is ready again**. This is important when changing a slider from `0` to `100`, for example. If it would send all intermediate values, it might take a while for your code to process everything, causing a noticeable lag. """metadatashow_logsèdisabled®skip_as_script«code_folded$de1b9643-66fa-4918-9a93-0f340c8548bacell_id$de1b9643-66fa-4918-9a93-0f340c8548bacodeٔmd""" Now we can use the script to handle whatever interaction we want. For a simple element, let's add a button and count the number of clicks. """metadatashow_logsèdisabled®skip_as_script«code_folded$82c7b1ea-08c0-495f-baba-37e5497abde2cell_id$82c7b1ea-08c0-495f-baba-37e5497abde2code!md""" It's as simple as that! """metadatashow_logsèdisabled®skip_as_script«code_folded$cb65a4ee-02e5-4779-8728-b994d8af645dcell_id$cb65a4ee-02e5-4779-8728-b994d8af645dcodetypeof(x)metadatashow_logsèdisabled®skip_as_script«code_folded$f558f689-bd7a-4c65-8b3d-b3681a4ed013cell_id$f558f689-bd7a-4c65-8b3d-b3681a4ed013code@bind limited_counter HTML("""
""")metadatashow_logsèdisabled®skip_as_script«code_folded$b6501bfb-5e1d-40b9-bd16-d38085d2611dcell_id$b6501bfb-5e1d-40b9-bd16-d38085d2611dcode!@bind e html""metadatashow_logsèdisabled®skip_as_script«code_folded$ced18648-7eb2-11ea-2052-07795685f0dacell_id$ced18648-7eb2-11ea-2052-07795685f0dacodeamd"#### JavaScript? Yes! We are using `Generator.input` from [`observablehq/stdlib`](https://github.com/observablehq/stdlib#Generators_input) to create a JS _Generator_ (kind of like an Observable) that listens to `onchange`, `onclick` or `oninput` events, [depending on the element type](https://github.com/observablehq/stdlib#Generators_input). This makes it super easy to create nice HTML/JS-based interaction elements - a package creator simply has to write a `show` method for MIME type `text/html` that creates a DOM object that triggers the `input` event. In other words, _Pluto's `@bind` will behave exactly like [`viewof` in observablehq](https://observablehq.com/@observablehq/introduction-to-views)_. _If you want to learn more about using Javascript in Pluto, check out the [JavaScript sample notebook](https://featured.plutojl.org/web/javascript)!_"metadatashow_logsèdisabled®skip_as_script«code_folded$e2854aa0-e3c5-423d-80d9-fc875c5dd54dcell_id$e2854aa0-e3c5-423d-80d9-fc875c5dd54dcodewmd""" Keep in mind that changing the value of `limit` will re-evaluate the slider cell, so it will reset the value. """metadatashow_logsèdisabled®skip_as_script«code_folded$bd24d02c-7eac-11ea-14ab-95021678e71ecell_id$bd24d02c-7eac-11ea-14ab-95021678e71ecode @bind x html""metadatashow_logsèdisabled®skip_as_script«code_folded$0a7018ca-2afe-42b1-850f-a649e570709fcell_id$0a7018ca-2afe-42b1-850f-a649e570709fcodefmd""" A neat aspect of this `@bind` macro is that on the Julia side, `x` is just a normal integer: """metadatashow_logsèdisabled®skip_as_script«code_folded$5301eb68-7f14-11ea-3ff6-1f075bf73955cell_id$5301eb68-7f14-11ea-3ff6-1f075bf73955codeٯmd""" ## Input types You can use binds with anything that fires an [`input` event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event). For example: """metadatashow_logsèdisabled®skip_as_script«code_folded$f595bdb6-bd15-4c62-9de6-49f14c7d365acell_id$f595bdb6-bd15-4c62-9de6-49f14c7d365acode@bind f html""metadatashow_logsèdisabled®skip_as_script«code_folded$d5b3adc5-2c99-4901-adf5-8d8579a32b51cell_id$d5b3adc5-2c99-4901-adf5-8d8579a32b51code6md""" !!! tip Interpolating values in Javascript is neat, but remember that we are just taking the string representation of the variable and pasting it in the javascript code. For some complex data types like dates, you will need to do a bit of conversion to turn them into proper javascript expressions. """metadatashow_logsèdisabled®skip_as_script«code_folded$c50a5e52-7c95-445c-86ee-c60104a39dbdcell_id$c50a5e52-7c95-445c-86ee-c60104a39dbdcodetmd""" ## Using Julia values in HTML We've seen how you can pass on values from an interactive HTML element on to Julia, but for proper interaction, we also want to do it the other way around! The most basic way to do this is string interpolation. In this example, you can change the value of `limit` in the code to affect the maximum value of the slider. Try it out! """metadatashow_logsèdisabled®skip_as_script«code_folded$3b6dc6d5-ce96-40f6-97f7-511ea6d49122cell_id$3b6dc6d5-ce96-40f6-97f7-511ea6d49122code@bind x2 myslidermetadatashow_logsèdisabled®skip_as_script«code_folded$5bd8b261-a89d-46a3-bb59-c95a1801c881cell_id$5bd8b261-a89d-46a3-bb59-c95a1801c881codecountermetadatashow_logsèdisabled®skip_as_script«code_folded$e3eb31ae-c512-426f-915c-01144edbc90dcell_id$e3eb31ae-c512-426f-915c-01144edbc90dcode@bind counter html"""
"""metadatashow_logsèdisabled®skip_as_script«code_folded$2cefd0de-db13-49c1-abeb-097792ef46f6cell_id$2cefd0de-db13-49c1-abeb-097792ef46f6codeٟmd""" For something even fancier, you can also interpolate value in Javascript. For example, here I have adapted my counter so it won't count past `limit`: """metadatashow_logsèdisabled®skip_as_script«code_folded$3297233b-9567-4d5e-8138-93ebe20fed48cell_id$3297233b-9567-4d5e-8138-93ebe20fed48codex1, x2metadatashow_logsèdisabled®skip_as_script«code_folded$cb1fd532-7eac-11ea-307c-ab16b1977819cell_id$cb1fd532-7eac-11ea-307c-ab16b1977819codexmetadatashow_logsèdisabled®skip_as_script«code_folded$9985a640-c1d3-48dc-b00b-d7500085a37bcell_id$9985a640-c1d3-48dc-b00b-d7500085a37bcodeo@bind d html""" """metadatashow_logsèdisabled®skip_as_script«code_folded$816ea402-7eae-11ea-2134-fb595cca3068cell_id$816ea402-7eae-11ea-2134-fb595cca3068codemd""" Not an observable, callback, or something else that you need to wrap your head around. You can use `x` like you would any other number, and Pluto's reactivity means anything depending on `x` will be updated with it. 🚀 """metadatashow_logsèdisabled®skip_as_script«code_folded$d38d06f2-90ce-4e5a-9218-f5a52812e4a2cell_id$d38d06f2-90ce-4e5a-9218-f5a52812e4a2code$@bind c html""metadatashow_logsèdisabled®skip_as_script«code_folded$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecfcell_id$6b9a590b-ce24-4a9a-b5b4-5b353e6ccecfcodeYmd""" Okay, now we can use this HTML snippet with a `@bind` macro and see the result! """metadatashow_logsèdisabled®skip_as_script«code_folded$1a338f77-d8f3-4569-a2d5-c174368a4761cell_id$1a338f77-d8f3-4569-a2d5-c174368a4761codeH@bind limited HTML(""" """)metadatashow_logsèdisabled®skip_as_script«code_folded$c5a5e243-39d6-43d9-8de7-887661ba99cdcell_id$c5a5e243-39d6-43d9-8de7-887661ba99cdcode@bind x1 myslidermetadatashow_logsèdisabled®skip_as_script«code_folded$ff3abf71-cff6-459d-a622-0ec0ca8f164bcell_id$ff3abf71-cff6-459d-a622-0ec0ca8f164bcode+md""" This is is how the `PlutoUI` package works - it defines HTML literals - sometimes with their own scripts. If you've written some cool HTML inputs and you want to share them with others, you can also make a UI package! Just publish those definitions as a Julia package and you're done! ✨ """metadatashow_logsèdisabled®skip_as_script«code_folded$bb4b557b-e4fc-45f3-9d1f-060198167bfacell_id$bb4b557b-e4fc-45f3-9d1f-060198167bfacodeٻmd""" ## Reusing elements Once you've written some neat interactive element, you may want to use it a few times in notebook. The easiest way is to put the HTML literal in a variable. """metadatashow_logsèdisabled®skip_as_script«code_folded$8f829274-7eb1-11ea-3888-13c00b3ba70fcell_id$8f829274-7eb1-11ea-3888-13c00b3ba70fcodemd"""### What does the macro do? The `@bind` macro does not actually contain the interactivity mechanism, this is built into Pluto itself. Still, it does two things: it assigns a _default value_ to the variable (`missing` in most cases), and it wraps the second argument in a `PlutoRunner.Bond` object. For example, _expanding_ the `@bind` macro turns this expression: ```julia @bind x Slider(5:15) ``` into (simplified): ```julia begin local el = Slider(5:15) global x = AbstractPlutoDingetjes.intial_value(el) PlutoRunner.create_bond(el, :x) end ``` We see that the macro creates a variable `x`, which is given the value `AbstractPlutoDingetjes.intial_value(el)`. This function returns `missing` by default, unless a method was implemented for your widget type. For example, `PlutoUI` has a `Slider` type, and it defines a method for `intial_value(slider::Slider)` that returns the default number. Declaring a default value using `AbstractPlutoDingetjes` is **not necessary**, as shown by the earlier examples in this notebook, but the default value will be used for `x` if the `notebook.jl` file is _run as a plain julia file_, without Pluto's interactivity. You don't need to worry about this if you are just getting started with Pluto and interactive elements, but more advanced users should take a look at [`AbstractPlutoDingetjes.jl`](https://github.com/JuliaPluto/AbstractPlutoDingetjes.jl). """metadatashow_logsèdisabled®skip_as_script«code_folded$ede8009e-7f15-11ea-192a-a5c6135a9dcfcell_id$ede8009e-7f15-11ea-192a-a5c6135a9dcfcode(a, b, c, d, e, f)metadatashow_logsèdisabled®skip_as_script«code_folded$c1b9fbbb-3629-4abf-b11a-b7345b01d403cell_id$c1b9fbbb-3629-4abf-b11a-b7345b01d403codemd""" ## Scripting inputs with Javascript You can also use Javascript to write more complicated inputs. To get started with this, add a ` """metadatashow_logsèdisabled®skip_as_script«code_folded$2d8661f1-6f78-4161-a306-982e3ddf3646cell_id$2d8661f1-6f78-4161-a306-982e3ddf3646codeTmyslider = html"""""";metadatashow_logsèdisabled®skip_as_script«code_folded$db24490e-7eac-11ea-094e-9d3fc8f22784cell_id$db24490e-7eac-11ea-094e-9d3fc8f22784codemd""" ## Bound variables A basic interactive cell looks like this: we use the `@bind` macro, define a Julia variable, and add a bit of HTML code that creates an `` element. The HTML element will be rendered as the cell's output. """metadatashow_logsèdisabled®skip_as_script«code_folded$901c2b84-14b8-4deb-89d6-705a4972582ccell_id$901c2b84-14b8-4deb-89d6-705a4972582ccodelimited_countermetadatashow_logsèdisabled®skip_as_script«code_folded$2714a923-2be5-4cf9-97dd-75347968dfeecell_id$2714a923-2be5-4cf9-97dd-75347968dfeecodelimit = 5metadatashow_logsèdisabled®skip_as_script«code_folded$863c5996-9892-4bfc-96ba-225fa4a2266ccell_id$863c5996-9892-4bfc-96ba-225fa4a2266ccodemd""" !!! tip To avoid confusing your readers, it's a good idea to put a `;` at the end of the cell where you define the interactive element, like we did here. This way, we only show sliders that are actually bound to something. """metadatashow_logsèdisabled®skip_as_script«code_foldedënotebook_id$58dbcc0a-6f92-11f1-99dc-5f728e44b567in_temp_dir¨metadatafrontmatterlicense_urlghttps://github.com/JuliaPluto/featured/blob/2a6a9664e5428b37abe4957c1dca0994f4a8b7fd/LICENSES/UnlicenseauthornamePluto.jlurlhttps://github.com/JuliaPlutoimagedhttps://user-images.githubusercontent.com/6933510/174067982-904951c4-4bba-42c7-a340-102ceb7e8e10.pngorder1titleInteractivity with HTMLtagsinteractivityclassicweblicenseUnlicensedescription.Write your own interactive controls with HTML!